package com.itheima.filter;

import com.alibaba.fastjson.JSON;
import com.itheima.common.BaseContext;
import com.itheima.common.R;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.AntPathMatcher;

@Slf4j
@WebFilter(filterName = "loginCheckFilter",urlPatterns = "/*") //取名字 定义拦截所有
public class LoginCheckFilter implements Filter {

    //路径匹配器 ，支持通配符   避免 /backend/demo  与  /backend/index.html
    public static final AntPathMatcher PATH_MATCHER= new AntPathMatcher();

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        //向下转型
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;

        // 1.获取此次请求 URI
        String reqUrl = req.getRequestURI();  // /backend/index.html
                                              //         /xx.xx特殊
        log.info("拦截到：{}",reqUrl);

        // 2.定义需要放行的路径
        String[] urls =  new String[]{
                "/employee/login",  //登录
                "/employee/logout", //登出
                "/backend/**",      // backend包下
                "/front/**",        // front包下
                "/common/**",       // 文件上传路径
                "/user/sendMsg",    // 移动端发送短信
                "/user/login"       // 移动端登录

        };

        // 3. 判断本次请求是否需要处理 , 定义方法
        boolean check = check(urls, reqUrl);

        // 4.如果不需要处理，则直接放行
        if(check){
            log.info("静态资源本次请求不需要处理：{}",reqUrl);
            //放行
            chain.doFilter(req,resp);
            //结束方法
            return;
        }

        // 5-1.判断登录状态，如果已经登录，则直接放行
        if(req.getSession().getAttribute("emp") != null){ //session域中存入的id
            log.info("用户已登录,登录id为：{}",req.getSession().getAttribute("emp")+"..."+reqUrl);            //放行

            //获取线程id
            //long id = Thread.currentThread().getId();
            //log.info("线程id:{}",id);
            //将登录用户id获取到存入线程变量副本中
            Long empId = (Long) req.getSession().getAttribute("emp");
            BaseContext.setCurrentId(empId);

            chain.doFilter(req,resp);  //放行
            BaseContext.deleteId();    //防止内存泄漏
            //结束方法
            return;
        }

        // 5-2.判断移动端用户登录状态，如果已经登录，则直接放行
        if(req.getSession().getAttribute("user") != null){ //session域中存入的id
            log.info("移动端用户已登录,登录id为：{}",req.getSession().getAttribute("user")+"...路径："+reqUrl);            //放行

            //获取线程id
            //long id = Thread.currentThread().getId();
            //log.info("线程id:{}",id);
            //将登录用户id获取到存入线程变量副本中
            Long userId = (Long) req.getSession().getAttribute("user");
            BaseContext.setCurrentId(userId);

            chain.doFilter(req,resp);  //放行
            BaseContext.deleteId();    //防止内存泄漏
            //结束方法
            return;
        }

        // 6.如果未登录，则直接返回未登录结果 ,通过输出流方式向客户端响应数据
        log.info("用户未登录：{}",reqUrl);
        resp.getWriter().write(JSON.toJSONString(R.error("NOTLOGIN")));
        //结束方法
    }

    /**
     * 路径匹配，判断本次请求是否需要放行
     * @param urls
     * @param reqUrl
     * @return*/

    public boolean  check(String[] urls,String reqUrl){
        //遍历数组
        for (String url : urls) {
            //路径匹配器 ，支持通配符
            boolean flag = PATH_MATCHER.match(url, reqUrl);
            //判断路径是否匹配上了
            if(flag){
                //匹配上了，返回true
                return  true;
            }
        }
        //没有匹配上
        return false;
    }
}
